/**
 * 隧道工程计算算法实现
 * 提供隧道工程设计和分析中的基础计算功能
 * 包括隧道几何参数计算和工程特性分析
 */
export class TunnelAlgorithms {
  /**
   * 计算隧道的几何参数
   * 基于隧道入洞口和出洞口的三维坐标，计算隧道的水平长度、垂直高度、实际长度、坡度和朝向角度
   * 这些参数对于隧道设计、施工和安全评估至关重要
   * 
   * @param {number} entranceX 入洞口X坐标(m)，通常使用大地坐标系或工程坐标系
   * @param {number} entranceY 入洞口Y坐标(m)，通常使用大地坐标系或工程坐标系
   * @param {number} entranceZ 入洞口Z坐标(m)，通常表示高程或海拔
   * @param {number} exitX 出洞口X坐标(m)，通常使用大地坐标系或工程坐标系
   * @param {number} exitY 出洞口Y坐标(m)，通常使用大地坐标系或工程坐标系
   * @param {number} exitZ 出洞口Z坐标(m)，通常表示高程或海拔
   * @returns {{horizontalLenth: number, height: number, actualLenth: number, gradient: number, orientationAngle: number}} 隧道几何参数计算结果
   * @returns {number} return.horizontalLenth - 隧道水平投影长度(m)
   * @returns {number} return.height - 隧道垂直高度差(m)，取绝对值
   * @returns {number} return.actualLenth - 隧道实际长度(m)，空间直线距离
   * @returns {number} return.gradient - 隧道坡度，垂直变化量与水平长度的比值
   * @returns {number} return.orientationAngle - 隧道朝向角度(°)，从X轴正方向逆时针测量
   */
  static calculateTunnelLength(entranceX: number, entranceY: number, entranceZ: number, exitX: number, exitY: number, exitZ: number): { horizontalLenth: number, height: number, actualLenth: number, gradient: number, orientationAngle: number } {
    // 计算坐标差值，用于后续几何参数计算
    const deltaX = exitX - entranceX;
    const deltaY = exitY - entranceY;
    const deltaZ = exitZ - entranceZ;
    
    // 计算水平投影长度：二维欧几里得距离 √[(ΔX)² + (ΔY)²]
    const horizontalLenth = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
    
    // 计算垂直高度差：取Z坐标差的绝对值
    const height = Math.abs(deltaZ);
    
    // 计算隧道实际长度：三维欧几里得距离 √[(ΔX)² + (ΔY)² + (ΔZ)²]
    const actualLenth = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ);
    
    // 计算隧道坡度：垂直变化量与水平长度的比值
    // 避免除以零错误，当水平长度为零时坡度设为0
    const gradient = horizontalLenth !== 0 ? deltaZ / horizontalLenth : 0;
    
    // 计算隧道朝向角度：使用atan2函数计算，结果从弧度转换为角度
    // 角度范围为[-180, 180]，以X轴正方向为0度，逆时针为正
    const orientationAngle = Math.atan2(deltaY, deltaX) * 180 / Math.PI;
    
    // 返回计算结果对象，包含所有隧道几何参数
    return { horizontalLenth, height, actualLenth, gradient, orientationAngle };
  }

  /**
   * 计算隧道埋深类型和临界埋深
   * 根据围岩重度、实际埋深和岩石等级，判断隧道属于深埋还是浅埋类型
   * 并计算临界埋深值，为隧道设计和施工方案提供依据
   * 
   * @param {number} gamma 围岩重度(kN/m³)，表示岩石或土壤的单位体积重量
   * @param {number} H 隧道实际埋深(m)，从地表到隧道拱顶的垂直距离
   * @param {number} rockgrade 岩石等级(1-5)，表示岩石的坚硬程度和完整性
   * @returns {{depthtype: string, Hp: number, q: number}} 隧道埋深分析结果
   * @returns {string} return.depthtype - 隧道埋深类型，'深埋'或'浅埋'
   * @returns {number} return.Hp - 临界埋深值(m)，判断深埋和浅埋的界限值
   * @returns {number} return.q - 垂直均布荷载(kPa)，由围岩自重产生的压力
   */
  static TunnelDepth(gamma: number, H: number, rockgrade: number) {
    // 计算垂直均布荷载：围岩重度 × 实际埋深
    const q = gamma * H;
    // 计算等效高度：垂直均布荷载 ÷ 围岩重度
    const hq = q / gamma;
    
    // 根据岩石等级计算临界埋深Hp
    // 坚硬岩石(等级>3)采用较大的安全系数，软弱岩石采用较小的安全系数
    let Hp;
    if (rockgrade > 3) {
      Hp = 2.5 * hq; 
    } else {
      Hp = 2 * hq; 
    }
    
    // 判断隧道埋深类型：当实际埋深大于临界埋深时为深埋，否则为浅埋
    let depthtype;
    if (H > Hp) {
      depthtype = '深埋';
    } else {
      depthtype = '浅埋';
    }
    
    // 返回分析结果，包括埋深类型、临界埋深和垂直均布荷载
    return { depthtype, Hp, q };
  }

  /**
   * 计算隧道洞口高程和里程
   * 根据入洞口高程、出洞口高程、明暗线长度和坡度，计算洞口相关参数
   * 
   * @param {number} entranceZ 入洞口高程(m)
   * @param {number} entranceY 入洞口Y坐标(m)，通常表示水平距离或投影长度
   * @param {number} entrancelinelenth 入洞口明暗线长度(m)
   * @param {number} exitZ 出洞口高程(m)
   * @param {number} exitY 出洞口Y坐标(m)，通常表示水平距离或投影长度
   * @param {number} exitlinelenth 出洞口明暗线长度(m)
   * @param {number} slope 坡度，tan值
   * @returns {{entrancelinesmileage: number, entranceelevation: number, exitlinesmileage: number, exitelevation: number}} 洞口参数计算结果
   */
  static calculateTunnelEntranceExitElevation(entranceZ: number,entranceY:number, entrancelinelenth: number, exitZ: number,exitY:number, exitlinelenth: number, slope: number) {
    // 计算入洞口明暗线里程：从洞口向洞内延伸，取负值
    const entrancelinesmileage = entranceY + entrancelinelenth;
    
    // 计算入洞口明暗线底板高程：基于入洞口高程和坡度
    const entranceelevation = entranceZ + slope * entrancelinelenth;
    
    // 计算出洞口明暗线里程：从洞口向洞内延伸，取正值
    const exitlinesmileage = exitY + exitlinelenth;
    
    // 计算出洞口明暗线底板高程：基于出洞口高程和坡度
    const exitelevation = exitZ - slope * exitlinelenth;
    
    return {
      entrancelinesmileage,
      entranceelevation,
      exitlinesmileage,
      exitelevation
    };
  }
}

